package com.mostka.wsrpc.server;

import com.mostka.rpc.server.WsRpcServerServlet;
import com.mostka.wsrpc.client.TestWsClient;
import com.mostka.wsrpc.client.TestWsServer;
import com.mostka.wsrpc.shared.Channels;
import com.mostka.wsrpc.shared.Messenger;

import java.util.HashMap;

@SuppressWarnings("serial")
public class Server extends WsRpcServerServlet implements TestWsServer {
	
	// class to handle user info and connection
    class Client{
        public TestWsClient client;
        public Messenger messenger;
        Client(TestWsClient client, Messenger messenger) {
            this.client = client;
            this.messenger = messenger;
        }
    }
    // init channel list with clients(users) indexed by client token 
    HashMap<String, HashMap<Integer, Client>> clients = new HashMap<String, HashMap<Integer, Client>>(){{
        for (String channel : Channels.values) {
            put(channel, new HashMap<Integer, Client>());
        }
    }};

    // handle client connect
	public void onJoin(String channel, TestWsClient client) {
		synchronized(clients){
	        if (!clients.containsKey(channel)){
	            disconnect(client.getClientId(),0,"badChannel");
	            return;
	        }
	        int clientId = client.getClientId();
	        Messenger messenger = new Messenger(clientId,"anonim");
	        Client client2 = new Client(client, messenger);
	        // get clients list on current channel
	        HashMap<Integer, Client> map = clients.get(channel);
	        // put client to clients list
	        map.put(clientId,client2);
		}
    }
	// handle client disconnect
	public void onClose(String channelName, int clientId) {
		synchronized(clients){
			// get clients list on current channel
	        HashMap<Integer, Client> clientsss = clients.get(channelName);
	        Client client = clientsss.get(clientId);
	        if (client!=null){
	        	// remove client from clients list
	            clientsss.remove(clientId);
	            // send message to all client about client disconnect
	            for (Client client1 : clientsss.values()) {
	            	client1.client.onMessengerDisconnect(clientId);
	            }
	        }
		}
	}
	// ==================== handle TestWsServer (calls from client) ==============//
    // send message to all
    public void sendToAll(String channel, TestWsClient sender, String message) {
		// get clients list on current channel
        HashMap<Integer, Client> clientsss = clients.get(channel);
        for (Client recipient : clientsss.values()) {
            if (recipient.client.getClientId()!=sender.getClientId()){
                recipient.client.onMessage(sender.getClientId(),message);
            }
        }
    }

    // send message to defined user
    public void sendTo(String channel, TestWsClient sender, int recipientId, String message) {
        Client recipient = clients.get(channel).get(recipientId);
        if (recipient != null) {
            recipient.client.onMessage(sender.getClientId(),message);
        }
    }

    // retrieved user name, so we can join him and send message to all user abount new user connected
    public void join(String channel, TestWsClient wsClient, String nick) {
    	synchronized(clients){
	        Client client = clients.get(channel).get(wsClient.getClientId());
	        if (client != null) {
	            client.messenger=new Messenger(wsClient.getClientId(),nick);
	        }
			// get clients list on current channel
	        HashMap<Integer, Client> clientsss = clients.get(channel);
	        for (Client recipient : clientsss.values()) {
	            if (recipient.client.getClientId()!=wsClient.getClientId()){
	                recipient.client.onMessengerJoin(client.messenger);
	            }
	        }
    	}
    }

	// client ask for client list, so send him it back
	public void getMessengers(String channel, TestWsClient wsClient) {
		synchronized(clients){
			HashMap<Integer, Client> clientsss = clients.get(channel);
			Messenger[] messengers = new Messenger[clientsss.size()-1];
			
			int pos = 0;
			for (Client recipient : clientsss.values()) {
	            if (recipient.client.getClientId()!=wsClient.getClientId()){
	                messengers[pos++] = recipient.messenger;
	            }
	        }
			wsClient.messengersRetrieved(messengers);
		}
	}
}
